﻿using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Transactions;
using BaseRepository;
using Extensions.Attribute.TransactionAttribute;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Extensions.Filters;

/// <summary>
/// 配合Transaction 标签使用的过滤器
/// </summary>
public class TransactionFilter:IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // 判断当前aciotn有没有加这个标签 如果加了  就开启事务 如果没加  那么就不开启
        var attribute = (context.ActionDescriptor as ControllerActionDescriptor)?.MethodInfo
            .GetCustomAttribute<TransactionAttribute>();
        if (attribute==null)
        {
            await next.Invoke();
            return;
        }
        // 开始 事务  这个事务支持嵌套和同一个数据库  context上下文  
        // TransactionScopeAsyncFlowOption 表示支持异步  应为  要判断同步异步  来把事务信息 方在threadlocal还是asynclocal
        // TransactionOptions 设置事务的隔离级别  rc就够了
        // scopeOption:TransactionScopeOption.Required 该范围需要一个事务。 如果已经存在事务，则使用该事务
        using var transaction = new  TransactionScope(scopeOption:TransactionScopeOption.Required,
            transactionOptions:new TransactionOptions()
            {
                IsolationLevel = IsolationLevel.ReadCommitted
            },asyncFlowOption: TransactionScopeAsyncFlowOption.Enabled);
        var reslut = await next.Invoke();
        // 这边报错  不会抛出到上层  只能从result中来读取
        if (reslut.Exception==null)
        {
            transaction.Complete();
        }
        // 释放的时候没有 complete的话 就会自动回滚  
    }
}